package qinggui.mlz.smsservice.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import qinggui.mlz.smsservice.entity.Sms;
import qinggui.mlz.smsservice.infrastructure.SmsTemplate;
import qinggui.mlz.smsservice.mapper.SmsMapper;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class SmsService {
    @Autowired
    private SmsMapper smsMapper;
    @Autowired
    private SmsTemplate smsTemplate;
    // ThreadPoolExecutor的包装类，构造方法注入
    private final ThreadPoolTaskExecutor smsExecutor;

    public SmsService(ThreadPoolTaskExecutor smsExecutor) {
        this.smsExecutor = smsExecutor;
        smsExecutor.setWaitForTasksToCompleteOnShutdown(true);//shutdown关闭时等待所有任务完成
        smsExecutor.setCorePoolSize(10);
        smsExecutor.setMaxPoolSize(20);
        smsExecutor.setQueueCapacity(100);
        smsExecutor.setThreadNamePrefix("sms-");
        smsExecutor.initialize();
    }

    /**
     * 同步发送短信
     *
     * @param mobile 手机号
     * @return String
     */
    @Transactional
    public String sendMessage(String mobile) {
        // 1. 生成 6 位随机数字验证码
        String code = RandomStringUtils.randomNumeric(6);
        // 2. 真正发送
        String result = smsTemplate.send(mobile, code);
        LocalDateTime now = LocalDateTime.now();
        Sms sms = new Sms().setPhone(mobile)
                .setContent("【清规】验证码：" + code)
                .setResult(result)
                .setSendTime(now)
                .setIsDeleted(Byte.valueOf("0"))
                .setCreateTime(now)
                .setUpdateTime(now);
        smsMapper.create(sms);
        if ("OK".equals(result)) {
            return "发送成功";
        } else {
            return "发送失败：" + result;
        }
    }

    /**
     * 多线程同步发送（批量发送）
     *
     * @param phones 手机号列表
     * @return String
     */
    public String sendBatchSms(List<String> phones) {
        if (phones == null || phones.isEmpty()) {
            throw new RuntimeException("手机号列表不能为空");
        }
        // 创建CountDownLatch, 手机号数量，用于主线程等待所有子线程完事
        CountDownLatch latch = new CountDownLatch(phones.size());
        // 线程安全的失败列表
        List<String> errorPhones = Collections.synchronizedList(new ArrayList<>());
        for (String phone : phones) {
            // 异步执行，不阻塞主线程
            smsExecutor.execute(() -> {
                try {
                    String code = RandomStringUtils.randomNumeric(6);
                    String result = smsTemplate.send(phone, code);
                    LocalDateTime now = LocalDateTime.now();
                    Sms sms = new Sms().setPhone(phone)
                            .setContent("【清规】验证码：" + code)
                            .setResult(result)
                            .setSendTime(now)
                            .setIsDeleted(Byte.valueOf("0"))
                            .setCreateTime(now)
                            .setUpdateTime(now);
                    Integer insertRows = smsMapper.create(sms);
                    // 如果插入失败，则跳过
                    if (insertRows != 1) {
                        errorPhones.add(phone);
                        log.error("手机号插入数据库失败：{}", phone);
                    }
                    if (!"OK".equals(result)) {
                        // 短信发送失败
                        errorPhones.add(phone);
                    }
                } catch (Exception e) {
                    log.error("短信发送或入库异常，phone={}", phone, e);
                    errorPhones.add(phone);
                } finally {
                    // 无论成功、异常，都必须减门闩，防止主线程永远等待
                    latch.countDown();
                }
            });
        }
        try {
            // 主线程最多等待 30 秒；若提前发完（门闩归0）立即放行
            latch.await(30, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            // 1. 恢复中断标志
            Thread.currentThread().interrupt();
            // 2. 记录日志、提前返回、抛自定义异常
            log.warn("批量短信发送被中断", e);
            return "发送被取消";
        }
        String strPhones = errorPhones.toString();
        return errorPhones.isEmpty() ? "发送成功" : errorPhones.size() == phones.size() ? "发送失败：" + strPhones : "部分发送失败，发送失败的手机号：" + strPhones;
    }
}
